package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private Client client;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private AliIoTConfigProperties  aliIoTConfigProperties;

    @Autowired
    private DeviceMapper  deviceMapper;
    @Override
    public void syncProductList() {
        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(1);
        request.setPageSize(100);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductListResponse response = null;

        try {
         response = client.queryProductList(request);
        } catch (Exception e) {
        throw new BaseException(BasicEnum.IOT_LIST_PRODUCT_ERROR);
        }

        if(!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo().
                stream().map(p -> BeanUtil.toBean(p, ProductVo.class))
                .collect(Collectors.toList());
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));
    }

    @Override
    public List<ProductVo> queryProductList() {
        String productListStr = (String) redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
        if(ObjectUtil.isEmpty(productListStr)){
            return Collections.emptyList();
        }

        return JSONUtil.toList(productListStr, ProductVo.class);
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());

        if(count > 0){
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }

        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        if(!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        QueryProductRequest request2 = new QueryProductRequest();
        request2.setProductKey(deviceDto.getProductKey());
        request2.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse response2 = null;

        try {
            // 这里主要是前端没有传递产品名称productName，
            // 所以这里调用阿里云的接口，查询一下产品信息得到对应的productName
            response2 = client.queryProduct(request2);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
        }

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(response.getBody().getData().getIotId());
        device.setProductName(response2.getBody().getData().getProductName());

        if(device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }
        deviceMapper.insertSelective(device);
    }

    @Override
    public PageResponse<DeviceVo> PageDeviceList(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        Page<DeviceVo> page = deviceMapper.PageDeviceList(devicePageQueryDto);
        return PageResponse.of(page, DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceById(QueryDeviceDetailRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response = null;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        if(!response.getBody().getSuccess()){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        DeviceVo deviceVo = deviceMapper.selectByIotId(request.getIotId());
        BeanUtil.copyProperties(response.getBody().getData(), deviceVo);
        return deviceVo;
    }

    /**
     * 查看指定产品的已发布物模型中的功能定义详情
     *
     * @param request 查询已发布物模型请求模型
     * @return 已发布物模型中的功能定义详情
     */
    @Override
    public ResponseResult<QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData> queryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response = null;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        return ResponseResult.success(response.getBody().getData());
    }

    @Override
    public void UpdateDevice(DeviceDto deviceDto) {
        Long id = deviceDto.getId();
        Device DBdevice = deviceMapper.selectByPrimaryKey(id);
        if(ObjectUtil.isEmpty(DBdevice)){
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        //如果是随身设备，物理位置设为-1
        if (device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())) {
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        //更新数据库中设备信息
        deviceMapper.updateByPrimaryKeySelective(device);

        //调用物联网接口，更新云服务设备信息，这里只会更新阿里云那边的昵称，产品分类和设备名称一旦创建不允许再修改
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response = null;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

    }

    @Override
    public void deleteDevice(DeleteDeviceRequest request) {
        //删除数据库中设备信息
        deviceMapper.deleteByIotId(request.getIotId());

        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse response = null;
        try {
            response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

    }

    @Override
    public ResponseResult<QueryDevicePropertyStatusResponseBody.
            QueryDevicePropertyStatusResponseBodyData>
    queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response = null;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        if (!response.getBody().getSuccess()) {
            throw new RuntimeException(response.getBody().getErrorMessage());
        }
        return ResponseResult.success(response.getBody().getData());
    }
}
